1use std::num::NonZero;
2
3use crate::common::Rational32;
4
5#[derive(Clone, Copy, Hash, PartialEq, Eq)]
7pub struct ObjectHandle {
8 pub(crate) internal: aviutl2_sys::plugin2::OBJECT_HANDLE,
9}
10impl std::fmt::Debug for ObjectHandle {
11 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12 f.debug_tuple("ObjectHandle").field(&self.internal).finish()
13 }
14}
15impl From<aviutl2_sys::plugin2::OBJECT_HANDLE> for ObjectHandle {
16 fn from(value: aviutl2_sys::plugin2::OBJECT_HANDLE) -> Self {
17 Self { internal: value }
18 }
19}
20impl From<ObjectHandle> for aviutl2_sys::plugin2::OBJECT_HANDLE {
21 fn from(value: ObjectHandle) -> Self {
22 value.internal
23 }
24}
25
26unsafe impl Send for ObjectHandle {}
28unsafe impl Sync for ObjectHandle {}
29
30#[derive(Clone, Copy, Hash, PartialEq, Eq)]
32pub struct EffectHandle {
33 pub(crate) internal: aviutl2_sys::plugin2::EFFECT_HANDLE,
34}
35impl std::fmt::Debug for EffectHandle {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 f.debug_tuple("EffectHandle").field(&self.internal).finish()
38 }
39}
40impl From<aviutl2_sys::plugin2::EFFECT_HANDLE> for EffectHandle {
41 fn from(value: aviutl2_sys::plugin2::EFFECT_HANDLE) -> Self {
42 Self { internal: value }
43 }
44}
45impl From<EffectHandle> for aviutl2_sys::plugin2::EFFECT_HANDLE {
46 fn from(value: EffectHandle) -> Self {
47 value.internal
48 }
49}
50
51unsafe impl Send for EffectHandle {}
53unsafe impl Sync for EffectHandle {}
54
55#[derive(Debug, Clone)]
61#[non_exhaustive]
62pub struct EditInfo {
63 pub width: usize,
65 pub height: usize,
67 pub fps: Rational32,
69 pub sample_rate: usize,
71 pub frame: usize,
73 pub layer: usize,
75 pub frame_max: usize,
77 pub layer_max: usize,
79 pub display_frame: std::ops::Range<usize>,
86 pub display_layer: std::ops::Range<usize>,
93 pub select_range: Option<std::ops::RangeInclusive<usize>>,
96 pub scene_id: i32,
98}
99
100impl EditInfo {
101 pub unsafe fn from_raw(ptr: *const aviutl2_sys::plugin2::EDIT_INFO) -> Self {
105 let raw = unsafe { &*ptr };
106 Self {
107 width: raw.width as usize,
108 height: raw.height as usize,
109 fps: Rational32::new(raw.rate, raw.scale),
110 sample_rate: raw.sample_rate as usize,
111 frame: raw.frame as usize,
112 layer: raw.layer as usize,
113 frame_max: raw.frame_max as usize,
114 layer_max: raw.layer_max as usize,
115 display_frame: raw.display_frame_start as usize
116 ..(raw.display_frame_start + raw.display_frame_num) as usize,
117 display_layer: raw.display_layer_start as usize
118 ..(raw.display_layer_start + raw.display_layer_num) as usize,
119
120 select_range: if raw.select_range_start >= 0 && raw.select_range_end >= 0 {
121 Some(raw.select_range_start as usize..=raw.select_range_end as usize)
122 } else {
123 None
124 },
125
126 scene_id: raw.scene_id,
127 }
128 }
129}
130
131#[derive(Debug, Clone, Copy)]
133pub struct ObjectLayerFrame {
134 pub layer: usize,
135 pub start: usize,
136 pub end: usize,
137}
138
139impl ObjectLayerFrame {
140 pub fn frame_range(&self) -> std::ops::Range<usize> {
142 self.start..(self.end + 1)
143 }
144
145 pub fn frame_range_inclusive(&self) -> std::ops::RangeInclusive<usize> {
147 self.start..=self.end
148 }
149}
150
151#[derive(Debug, Clone, Copy)]
153pub struct LayerFrameData {
154 pub layer: usize,
155 pub frame: usize,
156}
157
158#[derive(Debug, Clone, Copy)]
159pub struct MediaInfo {
160 pub video_track_num: Option<NonZero<usize>>,
162 pub audio_track_num: Option<NonZero<usize>>,
164 pub total_time: f64,
166 pub width: usize,
168 pub height: usize,
170}
171
172#[derive(Debug, Clone)]
174pub struct TrackInfo {
175 pub mode: Option<String>,
178 pub params: Vec<f64>,
180 pub accelerate: bool,
182 pub decelerate: bool,
184 pub twopoint: bool,
186 pub timecontrol: bool,
188 pub group_num: usize,
191 pub group_index: usize,
193 pub group_name: Option<String>,
195}
196
197#[derive(Debug, Clone, PartialEq, Eq)]
199pub struct PaletteInfo {
200 pub colors: [PaletteColor; Self::PALETTE_NUM],
202}
203
204impl PaletteInfo {
205 pub const PALETTE_NUM: usize = aviutl2_sys::plugin2::PALETTE_INFO::PALETTE_NUM;
207
208 fn from_raw(raw: aviutl2_sys::plugin2::PALETTE_INFO) -> Self {
209 Self {
210 colors: raw.color.map(|color| PaletteColor {
211 r: color.r,
212 g: color.g,
213 b: color.b,
214 a: color.a,
215 }),
216 }
217 }
218
219 fn to_raw(&self) -> aviutl2_sys::plugin2::PALETTE_INFO {
220 let colors: [aviutl2_sys::plugin2::PALETTE_INFO_COLOR; Self::PALETTE_NUM] = self
221 .colors
222 .iter()
223 .map(|color| aviutl2_sys::plugin2::PALETTE_INFO_COLOR {
224 r: color.r,
225 g: color.g,
226 b: color.b,
227 a: color.a,
228 })
229 .collect::<Vec<_>>()
230 .try_into()
231 .expect("PaletteInfo colors length mismatch");
232 aviutl2_sys::plugin2::PALETTE_INFO { color: colors }
233 }
234}
235
236#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
238pub struct PaletteColor {
239 pub r: u8,
240 pub g: u8,
241 pub b: u8,
242 pub a: u8,
243}
244
245#[derive(Debug, Clone, Copy)]
247pub enum MediaFileSupportMode {
248 ExtensionOnly,
250 Strict,
252}
253
254#[derive(Debug, Clone, Copy, PartialEq)]
260pub struct BpmInfo {
261 pub tempo: f32,
263 pub beat: i32,
265 pub start: f64,
267 pub offset: f32,
269}
270impl PartialOrd for BpmInfo {
271 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
272 if self.start == other.start {
273 None
274 } else {
275 self.start.partial_cmp(&other.start)
276 }
277 }
278}
279impl From<aviutl2_sys::plugin2::BPM_INFO> for BpmInfo {
280 fn from(value: aviutl2_sys::plugin2::BPM_INFO) -> Self {
281 Self {
282 tempo: value.tempo,
283 beat: value.beat,
284 start: value.start,
285 offset: value.offset,
286 }
287 }
288}
289impl From<BpmInfo> for aviutl2_sys::plugin2::BPM_INFO {
290 fn from(value: BpmInfo) -> Self {
291 Self {
292 tempo: value.tempo,
293 beat: value.beat,
294 start: value.start,
295 offset: value.offset,
296 }
297 }
298}
299
300#[derive(thiserror::Error, Debug)]
302pub enum EditSectionError {
303 #[error("api call failed")]
304 ApiCallFailed,
305 #[error("object does not exist")]
306 ObjectDoesNotExist,
307 #[error("effect does not exist")]
308 EffectDoesNotExist,
309 #[error("input utf-8 string contains null byte")]
310 InputCstrContainsNull(#[from] std::ffi::NulError),
311 #[error("input utf-16 string contains null byte")]
312 InputCwstrContainsNull(#[from] crate::common::NullByteError),
313 #[error("value is out of range")]
314 ValueOutOfRange(#[from] std::num::TryFromIntError),
315 #[error("api returned non-utf8 data")]
316 NonUtf8Data(#[from] std::str::Utf8Error),
317
318 #[cfg(feature = "aviutl2-alias")]
319 #[error("alias parse error: {0}")]
320 ParseFailed(#[from] aviutl2_alias::TableParseError),
321}
322
323#[derive(thiserror::Error, Debug)]
325pub enum EditSectionParsedError<E: std::error::Error + Send + Sync + 'static> {
326 #[error(transparent)]
327 EditSectionError(#[from] EditSectionError),
328 #[error("value parse error: {0}")]
329 ParseError(E),
330}
331
332pub type EditSectionResult<T> = Result<T, EditSectionError>;
333
334#[derive(Debug)]
336pub struct ReadSection {
337 pub(crate) internal: *mut aviutl2_sys::plugin2::EDIT_SECTION,
338}
339
340#[derive(Debug)]
342pub struct EditSection {
343 pub info: EditInfo,
345
346 pub(crate) internal: *mut aviutl2_sys::plugin2::EDIT_SECTION,
347 read_section: ReadSection,
348}
349
350impl std::ops::Deref for EditSection {
351 type Target = ReadSection;
352
353 fn deref(&self) -> &Self::Target {
354 &self.read_section
355 }
356}
357
358impl ReadSection {
359 pub unsafe fn from_raw(ptr: *mut aviutl2_sys::plugin2::EDIT_SECTION) -> Self {
365 Self { internal: ptr }
366 }
367
368 pub fn find_object_after(
375 &self,
376 layer: usize,
377 frame: usize,
378 ) -> EditSectionResult<Option<ObjectHandle>> {
379 let object_handle =
380 unsafe { ((*self.internal).find_object)(layer.try_into()?, frame.try_into()?) };
381 if object_handle.is_null() {
382 Ok(None)
383 } else {
384 Ok(Some(ObjectHandle {
385 internal: object_handle,
386 }))
387 }
388 }
389
390 pub fn count_object_effect(
392 &self,
393 object: ObjectHandle,
394 effect: &str,
395 ) -> EditSectionResult<usize> {
396 self.ensure_object_exists(object)?;
397 let c_effect = crate::common::CWString::new(effect)?;
398 let count =
399 unsafe { ((*self.internal).count_object_effect)(object.internal, c_effect.as_ptr()) };
400 Ok(count.try_into()?)
401 }
402
403 pub fn get_object_layer_frame(
405 &self,
406 object: ObjectHandle,
407 ) -> EditSectionResult<ObjectLayerFrame> {
408 self.ensure_object_exists(object)?;
409 let object = unsafe { ((*self.internal).get_object_layer_frame)(object.internal) };
410 Ok(ObjectLayerFrame {
411 layer: object.layer.try_into()?,
412 start: object.start.try_into()?,
413 end: object.end.try_into()?,
414 })
415 }
416
417 pub fn get_object_alias(&self, object: ObjectHandle) -> EditSectionResult<String> {
419 self.ensure_object_exists(object)?;
420 let alias_ptr = unsafe { ((*self.internal).get_object_alias)(object.internal) };
421 if alias_ptr.is_null() {
422 return Err(EditSectionError::ApiCallFailed);
423 }
424 let c_str = unsafe { std::ffi::CStr::from_ptr(alias_ptr) };
425 let alias = c_str.to_str()?.to_owned();
426 Ok(alias)
427 }
428
429 #[cfg(feature = "aviutl2-alias")]
431 pub fn get_object_alias_parsed(
432 &self,
433 object: ObjectHandle,
434 ) -> Result<aviutl2_alias::Table, EditSectionParsedError<aviutl2_alias::TableParseError>> {
435 let alias_str = self.get_object_alias(object)?;
436 let alias_data = alias_str
437 .parse()
438 .map_err(EditSectionParsedError::ParseError)?;
439 Ok(alias_data)
440 }
441
442 pub fn get_object_name(&self, object: ObjectHandle) -> EditSectionResult<Option<String>> {
444 self.ensure_object_exists(object)?;
445 let name_ptr = unsafe { ((*self.internal).get_object_name)(object.internal) };
446 if name_ptr.is_null() {
447 return Ok(None);
448 }
449 Ok(Some(unsafe { crate::common::load_wide_string(name_ptr) }))
450 }
451
452 pub fn get_object_effect_item(
454 &self,
455 object: ObjectHandle,
456 effect_name: &str,
457 effect_index: usize,
458 item: &str,
459 ) -> EditSectionResult<String> {
460 self.ensure_object_exists(object)?;
461 let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
462 let c_item = crate::common::CWString::new(item)?;
463 let value_ptr = unsafe {
464 ((*self.internal).get_object_item_value)(
465 object.internal,
466 c_effect_name.as_ptr(),
467 c_item.as_ptr(),
468 )
469 };
470 if value_ptr.is_null() {
471 return Err(EditSectionError::ApiCallFailed);
472 }
473 let c_str = unsafe { std::ffi::CStr::from_ptr(value_ptr) };
474 let value = c_str.to_str()?.to_owned();
475 Ok(value)
476 }
477
478 #[cfg(feature = "aviutl2-alias")]
480 pub fn get_object_effect_item_parsed<T: aviutl2_alias::FromTableValue>(
481 &self,
482 object: ObjectHandle,
483 effect_name: &str,
484 effect_index: usize,
485 item: &str,
486 ) -> Result<T, EditSectionParsedError<<T as aviutl2_alias::FromTableValue>::Err>>
487 where
488 <T as aviutl2_alias::FromTableValue>::Err: std::error::Error + Sync + Send + 'static,
489 {
490 let value_str = self.get_object_effect_item(object, effect_name, effect_index, item)?;
491 T::from_table_value(&value_str).map_err(EditSectionParsedError::ParseError)
492 }
493
494 pub fn get_focused_object(&self) -> EditSectionResult<Option<ObjectHandle>> {
496 let object_handle = unsafe { ((*self.internal).get_focus_object)() };
497 if object_handle.is_null() {
498 Ok(None)
499 } else {
500 Ok(Some(ObjectHandle {
501 internal: object_handle,
502 }))
503 }
504 }
505
506 pub fn get_selected_objects(&self) -> EditSectionResult<Vec<ObjectHandle>> {
508 let mut handles = Vec::new();
509 let num_objects = unsafe { ((*self.internal).get_selected_object_num)() };
510 for i in 0..num_objects {
511 let object_handle = unsafe { ((*self.internal).get_selected_object)(i) };
512 if object_handle.is_null() {
513 return Err(EditSectionError::ApiCallFailed);
514 }
515 handles.push(ObjectHandle {
516 internal: object_handle,
517 });
518 }
519 Ok(handles)
520 }
521
522 pub fn is_support_media_file<P: AsRef<std::path::Path>>(
524 &self,
525 file_path: P,
526 mode: MediaFileSupportMode,
527 ) -> EditSectionResult<bool> {
528 let c_file_path = crate::common::CWString::new(&file_path.as_ref().to_string_lossy())?;
529 let is_supported = unsafe {
530 match mode {
531 MediaFileSupportMode::ExtensionOnly => {
532 ((*self.internal).is_support_media_file)(c_file_path.as_ptr(), false)
533 }
534 MediaFileSupportMode::Strict => {
535 ((*self.internal).is_support_media_file)(c_file_path.as_ptr(), true)
536 }
537 }
538 };
539 Ok(is_supported)
540 }
541
542 pub fn get_media_info<P: AsRef<std::path::Path>>(
544 &self,
545 file_path: P,
546 ) -> EditSectionResult<MediaInfo> {
547 let c_file_path = crate::common::CWString::new(&file_path.as_ref().to_string_lossy())?;
548 let mut media_info = std::mem::MaybeUninit::<aviutl2_sys::plugin2::MEDIA_INFO>::uninit();
549 let success = unsafe {
550 ((*self.internal).get_media_info)(
551 c_file_path.as_ptr(),
552 media_info.as_mut_ptr(),
553 std::mem::size_of::<aviutl2_sys::plugin2::MEDIA_INFO>() as i32,
554 )
555 };
556 if !success {
557 return Err(EditSectionError::ApiCallFailed);
558 }
559 let media_info = unsafe { media_info.assume_init() };
560 Ok(MediaInfo {
561 video_track_num: NonZero::new(media_info.video_track_num.try_into()?),
562 audio_track_num: NonZero::new(media_info.audio_track_num.try_into()?),
563 total_time: media_info.total_time,
564 width: media_info.width.try_into()?,
565 height: media_info.height.try_into()?,
566 })
567 }
568
569 pub fn get_layer_name(&self, layer: usize) -> EditSectionResult<Option<String>> {
571 let name_ptr = unsafe { ((*self.internal).get_layer_name)(layer.try_into()?) };
572 if name_ptr.is_null() {
573 return Ok(None);
574 }
575 Ok(Some(unsafe { crate::common::load_wide_string(name_ptr) }))
576 }
577
578 pub fn get_scene_name(&self) -> EditSectionResult<String> {
580 let name_ptr = unsafe { ((*self.internal).get_scene_name)() };
581 if name_ptr.is_null() {
582 return Err(EditSectionError::ApiCallFailed);
583 }
584 Ok(unsafe { crate::common::load_wide_string(name_ptr) })
585 }
586
587 pub fn get_layer_enable(&self, layer: usize) -> EditSectionResult<bool> {
589 let visible = unsafe { ((*self.internal).get_layer_enable)(layer.try_into()?) };
590 Ok(visible)
591 }
592
593 pub fn get_layer_lock(&self, layer: usize) -> EditSectionResult<bool> {
595 let locked = unsafe { ((*self.internal).get_layer_lock)(layer.try_into()?) };
596 Ok(locked)
597 }
598
599 pub fn get_object_section_num(&self, object: ObjectHandle) -> EditSectionResult<usize> {
601 self.ensure_object_exists(object)?;
602 let count = unsafe { ((*self.internal).get_object_section_num)(object.internal) };
603 Ok(count.try_into()?)
604 }
605
606 pub fn get_object_section_frame(
608 &self,
609 object: ObjectHandle,
610 section: usize,
611 ) -> EditSectionResult<usize> {
612 self.ensure_object_exists(object)?;
613 let frame = unsafe {
614 ((*self.internal).get_object_section_frame)(object.internal, section.try_into()?)
615 };
616 if frame == -1 {
617 Err(EditSectionError::ApiCallFailed)
618 } else {
619 Ok(frame.try_into()?)
620 }
621 }
622
623 pub fn get_object_section_frames(&self, object: ObjectHandle) -> EditSectionResult<Vec<usize>> {
630 self.ensure_object_exists(object)?;
631 let section_num = self.get_object_section_num(object)?;
632 let mut frames = Vec::new();
633 for section in 0..section_num {
634 frames.push(self.get_object_section_frame(object, section)?);
635 }
636 Ok(frames)
637 }
638
639 pub fn get_object_section_ranges(
641 &self,
642 object: ObjectHandle,
643 ) -> EditSectionResult<Vec<std::ops::Range<usize>>> {
644 self.ensure_object_exists(object)?;
645 let frames = self.get_object_section_frames(object)?;
646 let position = self.get_object_layer_frame(object)?;
647
648 Ok(frames
649 .iter()
650 .enumerate()
651 .map(|(i, &start)| {
652 let end = if i + 1 < frames.len() {
653 frames[i + 1]
654 } else {
655 position.end + 1
656 };
657 start..end
658 })
659 .collect())
660 }
661
662 pub fn get_object_track_value(
664 &self,
665 object: ObjectHandle,
666 effect_name: &str,
667 effect_index: usize,
668 item: &str,
669 frame: f64,
670 ) -> EditSectionResult<f64> {
671 self.ensure_object_exists(object)?;
672 let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
673 let c_item = crate::common::CWString::new(item)?;
674 let mut value = 0.0;
675 let success = unsafe {
676 ((*self.internal).get_object_track_value)(
677 object.internal,
678 c_effect_name.as_ptr(),
679 c_item.as_ptr(),
680 frame,
681 &mut value,
682 )
683 };
684 if !success {
685 return Err(EditSectionError::ApiCallFailed);
686 }
687 Ok(value)
688 }
689
690 pub fn get_object_check_value(
692 &self,
693 object: ObjectHandle,
694 effect_name: &str,
695 effect_index: usize,
696 item: &str,
697 frame: usize,
698 ) -> EditSectionResult<bool> {
699 self.ensure_object_exists(object)?;
700 let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
701 let c_item = crate::common::CWString::new(item)?;
702 let mut value = false;
703 let success = unsafe {
704 ((*self.internal).get_object_check_value)(
705 object.internal,
706 c_effect_name.as_ptr(),
707 c_item.as_ptr(),
708 frame.try_into()?,
709 &mut value,
710 )
711 };
712 if !success {
713 return Err(EditSectionError::ApiCallFailed);
714 }
715 Ok(value)
716 }
717
718 pub fn get_object_track_info(
721 &self,
722 object: ObjectHandle,
723 effect_name: &str,
724 effect_index: usize,
725 item: &str,
726 ) -> EditSectionResult<TrackInfo> {
727 self.ensure_object_exists(object)?;
728 let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
729 let c_item = crate::common::CWString::new(item)?;
730 let mut info = std::mem::MaybeUninit::<aviutl2_sys::plugin2::TRACK_INFO>::uninit();
731 let success = unsafe {
732 ((*self.internal).get_object_track_info)(
733 object.internal,
734 c_effect_name.as_ptr(),
735 c_item.as_ptr(),
736 info.as_mut_ptr(),
737 std::mem::size_of::<aviutl2_sys::plugin2::TRACK_INFO>() as i32,
738 )
739 };
740 if !success {
741 return Err(EditSectionError::ApiCallFailed);
742 }
743
744 let info = unsafe { info.assume_init() };
745 let mode = if info.mode.is_null() {
746 None
747 } else {
748 Some(unsafe { crate::common::load_wide_string(info.mode) })
749 };
750 let param_num: usize = info.param_num.try_into()?;
751 let params = if param_num == 0 {
752 Vec::new()
753 } else {
754 if info.param.is_null() {
755 return Err(EditSectionError::ApiCallFailed);
756 }
757 unsafe { std::slice::from_raw_parts(info.param, param_num) }.to_vec()
758 };
759
760 Ok(TrackInfo {
761 mode,
762 params,
763 accelerate: info.accelerate,
764 decelerate: info.decelerate,
765 twopoint: info.twopoint,
766 timecontrol: info.timecontrol,
767 group_num: info.group_num.try_into()?,
768 group_index: info.group_index.try_into()?,
769 group_name: if info.group_name.is_null() {
770 None
771 } else {
772 Some(unsafe { crate::common::load_wide_string(info.group_name) })
773 },
774 })
775 }
776
777 pub fn get_palette_name(&self) -> EditSectionResult<String> {
779 let name_ptr = unsafe { ((*self.internal).get_palette_name)() };
780 if name_ptr.is_null() {
781 return Err(EditSectionError::ApiCallFailed);
782 }
783 Ok(unsafe { crate::common::load_wide_string(name_ptr) })
784 }
785
786 pub fn get_palette_info(&self, name: &str) -> EditSectionResult<PaletteInfo> {
788 let c_name = crate::common::CWString::new(name)?;
789 let mut info = std::mem::MaybeUninit::<aviutl2_sys::plugin2::PALETTE_INFO>::uninit();
790 let success = unsafe {
791 ((*self.internal).get_palette_info)(
792 c_name.as_ptr(),
793 info.as_mut_ptr(),
794 std::mem::size_of::<aviutl2_sys::plugin2::PALETTE_INFO>() as i32,
795 )
796 };
797 if !success {
798 return Err(EditSectionError::ApiCallFailed);
799 }
800 Ok(PaletteInfo::from_raw(unsafe { info.assume_init() }))
801 }
802
803 pub fn get_current_palette_info(&self) -> EditSectionResult<PaletteInfo> {
805 let name = self.get_palette_name()?;
806 self.get_palette_info(&name)
807 }
808
809 pub fn get_font(&self, font_name: &str) -> EditSectionResult<*mut std::ffi::c_void> {
811 let c_font_name = crate::common::CWString::new(font_name)?;
812 let ptr = unsafe { ((*self.internal).get_font)(c_font_name.as_ptr()) };
813 if ptr.is_null() {
814 Err(EditSectionError::ApiCallFailed)
815 } else {
816 Ok(ptr)
817 }
818 }
819
820 pub fn get_object_track_group_names(
822 &self,
823 object: ObjectHandle,
824 effect_name: &str,
825 effect_index: usize,
826 group_name: &str,
827 ) -> EditSectionResult<Vec<String>> {
828 self.ensure_object_exists(object)?;
829 let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
830 let c_group_name = crate::common::CWString::new(group_name)?;
831 let item_num = unsafe {
832 ((*self.internal).get_object_track_group_names)(
833 object.internal,
834 c_effect_name.as_ptr(),
835 c_group_name.as_ptr(),
836 std::ptr::null_mut(),
837 0,
838 )
839 };
840 let item_num: usize = item_num.try_into()?;
841 if item_num == 0 {
842 return Ok(Vec::new());
843 }
844
845 let mut item_names = vec![std::ptr::null(); item_num];
846 let actual_item_num = unsafe {
847 ((*self.internal).get_object_track_group_names)(
848 object.internal,
849 c_effect_name.as_ptr(),
850 c_group_name.as_ptr(),
851 item_names.as_mut_ptr(),
852 item_names.len().try_into()?,
853 )
854 };
855 let actual_item_num: usize = actual_item_num.try_into()?;
856 if actual_item_num > item_names.len() {
857 return Err(EditSectionError::ApiCallFailed);
858 }
859 item_names.truncate(actual_item_num);
860
861 item_names
862 .into_iter()
863 .map(|item_name| {
864 if item_name.is_null() {
865 Err(EditSectionError::ApiCallFailed)
866 } else {
867 Ok(unsafe { crate::common::load_wide_string(item_name) })
868 }
869 })
870 .collect()
871 }
872
873 pub fn get_focus_object_section(&self) -> EditSectionResult<Option<usize>> {
875 let section = unsafe { ((*self.internal).get_focus_object_section)() };
876 if section == -1 {
877 Ok(None)
878 } else {
879 Ok(Some(section.try_into()?))
880 }
881 }
882
883 pub fn get_grid_bpm_list(&self) -> EditSectionResult<Vec<BpmInfo>> {
885 let mut bpm_info_list = Vec::<aviutl2_sys::plugin2::BPM_INFO>::new();
886 let bpm_size = std::mem::size_of::<aviutl2_sys::plugin2::BPM_INFO>().try_into()?;
887 let bpm_num =
888 unsafe { ((*self.internal).get_grid_bpm_list)(std::ptr::null_mut(), 0, bpm_size) };
889 if bpm_num <= 0 {
890 return Ok(vec![]);
891 }
892 bpm_info_list.resize_with(bpm_num as usize, || aviutl2_sys::plugin2::BPM_INFO {
893 tempo: 0.0,
894 beat: 0,
895 start: 0.0,
896 offset: 0.0,
897 });
898 let actual_bpm_num = unsafe {
899 ((*self.internal).get_grid_bpm_list)(
900 bpm_info_list.as_mut_ptr(),
901 bpm_info_list.len() as i32,
902 bpm_size,
903 )
904 };
905 if actual_bpm_num != bpm_num {
906 return Err(EditSectionError::ApiCallFailed);
907 }
908 let bpm_info_list = bpm_info_list.into_iter().map(BpmInfo::from).collect();
909 Ok(bpm_info_list)
910 }
911
912 pub fn find_effect(
914 &self,
915 object: ObjectHandle,
916 effect_name: &str,
917 effect_index: usize,
918 ) -> EditSectionResult<EffectHandle> {
919 self.ensure_object_exists(object)?;
920 let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
921 let handle =
922 unsafe { ((*self.internal).find_effect)(object.internal, c_effect_name.as_ptr()) };
923 if handle.is_null() {
924 return Err(EditSectionError::ApiCallFailed);
925 }
926 Ok(EffectHandle { internal: handle })
927 }
928
929 pub fn get_first_effect(&self, object: ObjectHandle) -> EditSectionResult<EffectHandle> {
931 self.ensure_object_exists(object)?;
932 let handle = unsafe { ((*self.internal).find_effect)(object.internal, std::ptr::null()) };
933 if handle.is_null() {
934 Err(EditSectionError::ApiCallFailed)
936 } else {
937 Ok(EffectHandle { internal: handle })
938 }
939 }
940
941 pub fn get_effects(&self, object: ObjectHandle) -> EditSectionResult<Vec<EffectHandle>> {
943 self.ensure_object_exists(object)?;
944 let mut effects = Vec::<aviutl2_sys::plugin2::EFFECT_HANDLE>::new();
945 let num_effects =
946 unsafe { ((*self.internal).get_effect_list)(object.internal, std::ptr::null_mut(), 0) };
947 if num_effects <= 0 {
948 return Err(EditSectionError::ApiCallFailed);
949 }
950
951 effects.resize_with(num_effects as usize, std::ptr::null_mut);
952 let actual_num_effects = unsafe {
953 ((*self.internal).get_effect_list)(
954 object.internal,
955 effects.as_mut_ptr(),
956 effects.len() as i32,
957 )
958 };
959 if actual_num_effects != num_effects {
960 return Err(EditSectionError::ApiCallFailed);
961 }
962 let effect_handles = effects
963 .into_iter()
964 .map(|handle| EffectHandle { internal: handle })
965 .collect();
966 Ok(effect_handles)
967 }
968
969 pub fn get_effect_enable(&self, effect: EffectHandle) -> EditSectionResult<bool> {
971 self.ensure_effect_exists(effect)?;
972 let enabled = unsafe { ((*self.internal).get_effect_enable)(effect.internal) };
973 Ok(enabled)
974 }
975
976 pub fn get_effect_lock(&self, effect: EffectHandle) -> EditSectionResult<bool> {
978 self.ensure_effect_exists(effect)?;
979 let locked = unsafe { ((*self.internal).get_effect_lock)(effect.internal) };
980 Ok(locked)
981 }
982
983 pub fn get_effect_item_value(
985 &self,
986 effect: EffectHandle,
987 item: &str,
988 ) -> EditSectionResult<String> {
989 self.ensure_effect_exists(effect)?;
990 let c_item = crate::common::CWString::new(item)?;
991 let value_ptr =
992 unsafe { ((*self.internal).get_effect_item_value)(effect.internal, c_item.as_ptr()) };
993 if value_ptr.is_null() {
994 return Err(EditSectionError::ApiCallFailed);
995 }
996 let c_str = unsafe { std::ffi::CStr::from_ptr(value_ptr) };
997 let value = c_str.to_str()?.to_owned();
998 Ok(value)
999 }
1000
1001 #[cfg(feature = "aviutl2-alias")]
1003 pub fn get_effect_item_value_parsed<T: aviutl2_alias::FromTableValue>(
1004 &self,
1005 effect: EffectHandle,
1006 item: &str,
1007 ) -> Result<T, EditSectionParsedError<<T as aviutl2_alias::FromTableValue>::Err>>
1008 where
1009 <T as aviutl2_alias::FromTableValue>::Err: std::error::Error + Sync + Send + 'static,
1010 {
1011 let value_str = self.get_effect_item_value(effect, item)?;
1012 T::from_table_value(&value_str).map_err(EditSectionParsedError::ParseError)
1013 }
1014
1015 pub fn get_effect_data_size(
1017 &self,
1018 effect: EffectHandle,
1019 item: &str,
1020 ) -> EditSectionResult<usize> {
1021 self.ensure_effect_exists(effect)?;
1022 let c_item = crate::common::CWString::new(item)?;
1023 let size = unsafe {
1024 ((*self.internal).get_effect_data_value)(
1025 effect.internal,
1026 c_item.as_ptr(),
1027 std::ptr::null_mut(),
1028 0,
1029 )
1030 };
1031 Ok(size.try_into()?)
1032 }
1033
1034 pub fn get_effect_data_value(
1036 &self,
1037 effect: EffectHandle,
1038 item: &str,
1039 ) -> EditSectionResult<Vec<u8>> {
1040 self.ensure_effect_exists(effect)?;
1041 let c_item = crate::common::CWString::new(item)?;
1042 let size = self.get_effect_data_size(effect, item)?;
1043 if size == 0 {
1044 return Ok(Vec::new());
1045 }
1046 let mut buffer = vec![0u8; size];
1047 let actual_size = unsafe {
1048 ((*self.internal).get_effect_data_value)(
1049 effect.internal,
1050 c_item.as_ptr(),
1051 buffer.as_mut_ptr() as *mut std::ffi::c_void,
1052 size.try_into()?,
1053 )
1054 };
1055 if actual_size != i32::try_from(size)? {
1056 return Err(EditSectionError::ApiCallFailed);
1057 }
1058 Ok(buffer)
1059 }
1060
1061 pub unsafe fn get_effect_data_value_as<T>(
1073 &self,
1074 effect: EffectHandle,
1075 item: &str,
1076 ) -> EditSectionResult<T> {
1077 let size = std::mem::size_of::<T>();
1078 let actual_size = self.get_effect_data_size(effect, item)?;
1079 if actual_size != size {
1080 return Err(EditSectionError::ApiCallFailed);
1081 }
1082 let value = unsafe {
1083 let mut value = std::mem::MaybeUninit::<T>::uninit();
1084 let actual_size = ((*self.internal).get_effect_data_value)(
1085 effect.internal,
1086 crate::common::CWString::new(item)?.as_ptr(),
1087 value.as_mut_ptr() as *mut std::ffi::c_void,
1088 size.try_into()?,
1089 );
1090 if actual_size != i32::try_from(size)? {
1091 return Err(EditSectionError::ApiCallFailed);
1092 }
1093 value.assume_init()
1094 };
1095 Ok(value)
1096 }
1097
1098 pub fn get_effect_track_value(
1100 &self,
1101 effect: EffectHandle,
1102 item: &str,
1103 frame: f64,
1104 ) -> EditSectionResult<f64> {
1105 self.ensure_effect_exists(effect)?;
1106 let c_item = crate::common::CWString::new(item)?;
1107 let mut value = 0.0;
1108 let success = unsafe {
1109 ((*self.internal).get_effect_track_value)(
1110 effect.internal,
1111 c_item.as_ptr(),
1112 frame,
1113 &mut value,
1114 )
1115 };
1116 if !success {
1117 return Err(EditSectionError::ApiCallFailed);
1118 }
1119 Ok(value)
1120 }
1121
1122 pub fn get_effect_check_value(
1124 &self,
1125 effect: EffectHandle,
1126 item: &str,
1127 frame: usize,
1128 ) -> EditSectionResult<bool> {
1129 self.ensure_effect_exists(effect)?;
1130 let c_item = crate::common::CWString::new(item)?;
1131 let mut value = false;
1132 let success = unsafe {
1133 ((*self.internal).get_effect_check_value)(
1134 effect.internal,
1135 c_item.as_ptr(),
1136 frame.try_into()?,
1137 &mut value,
1138 )
1139 };
1140 if !success {
1141 return Err(EditSectionError::ApiCallFailed);
1142 }
1143 Ok(value)
1144 }
1145
1146 pub fn get_effect_track_info(
1148 &self,
1149 effect: EffectHandle,
1150 item: &str,
1151 ) -> EditSectionResult<TrackInfo> {
1152 self.ensure_effect_exists(effect)?;
1153 let c_item = crate::common::CWString::new(item)?;
1154 let mut info = std::mem::MaybeUninit::<aviutl2_sys::plugin2::TRACK_INFO>::uninit();
1155 let success = unsafe {
1156 ((*self.internal).get_effect_track_info)(
1157 effect.internal,
1158 c_item.as_ptr(),
1159 info.as_mut_ptr(),
1160 std::mem::size_of::<aviutl2_sys::plugin2::TRACK_INFO>() as i32,
1161 )
1162 };
1163 if !success {
1164 return Err(EditSectionError::ApiCallFailed);
1165 }
1166
1167 let info = unsafe { info.assume_init() };
1168 let mode = if info.mode.is_null() {
1169 None
1170 } else {
1171 Some(unsafe { crate::common::load_wide_string(info.mode) })
1172 };
1173 let param_num: usize = info.param_num.try_into()?;
1174 let params = if param_num == 0 {
1175 Vec::new()
1176 } else {
1177 if info.param.is_null() {
1178 return Err(EditSectionError::ApiCallFailed);
1179 }
1180 unsafe { std::slice::from_raw_parts(info.param, param_num) }.to_vec()
1181 };
1182
1183 Ok(TrackInfo {
1184 mode,
1185 params,
1186 accelerate: info.accelerate,
1187 decelerate: info.decelerate,
1188 twopoint: info.twopoint,
1189 timecontrol: info.timecontrol,
1190 group_num: info.group_num.try_into()?,
1191 group_index: info.group_index.try_into()?,
1192 group_name: if info.group_name.is_null() {
1193 None
1194 } else {
1195 Some(unsafe { crate::common::load_wide_string(info.group_name) })
1196 },
1197 })
1198 }
1199
1200 pub fn get_effect_name(&self, effect: EffectHandle) -> EditSectionResult<String> {
1202 let name_ptr = unsafe { ((*self.internal).get_effect_name)(effect.internal) };
1203 if name_ptr.is_null() {
1204 return Err(EditSectionError::ApiCallFailed);
1205 }
1206 Ok(unsafe { crate::common::load_wide_string(name_ptr) })
1207 }
1208
1209 pub fn get_mark_frame_list(&self) -> EditSectionResult<Vec<usize>> {
1211 let num_frames = unsafe { ((*self.internal).get_mark_frame_list)(std::ptr::null_mut(), 0) };
1212 if num_frames < 0 {
1213 return Err(EditSectionError::ApiCallFailed);
1214 }
1215 let num_frames = num_frames.try_into()?;
1216 let mut frames = vec![0; num_frames];
1217 let actual_num_frames = unsafe {
1218 ((*self.internal).get_mark_frame_list)(frames.as_mut_ptr(), num_frames.try_into()?)
1219 };
1220 if actual_num_frames != i32::try_from(num_frames)? {
1221 return Err(EditSectionError::ApiCallFailed);
1222 }
1223 Ok(frames
1224 .into_iter()
1225 .map(|f| f.try_into())
1226 .collect::<Result<Vec<_>, _>>()?)
1227 }
1228
1229 pub fn get_mark_frame_memo(&self, frame: usize) -> EditSectionResult<String> {
1231 let c_memo_ptr = unsafe { ((*self.internal).get_mark_frame_memo)(frame.try_into()?) };
1232 if c_memo_ptr.is_null() {
1233 return Err(EditSectionError::ApiCallFailed);
1234 }
1235 let memo = unsafe { crate::common::load_wide_string(c_memo_ptr) };
1236 Ok(memo)
1237 }
1238
1239 pub fn object_exists(&self, object: ObjectHandle) -> bool {
1241 let object = unsafe { ((*self.internal).get_object_layer_frame)(object.internal) };
1242 object.layer != -1
1243 }
1244
1245 pub fn effect_exists(&self, effect: EffectHandle) -> bool {
1247 let name_ptr = unsafe { ((*self.internal).get_effect_name)(effect.internal) };
1248 !name_ptr.is_null()
1249 }
1250
1251 fn ensure_object_exists(&self, object: ObjectHandle) -> EditSectionResult<()> {
1252 if !self.object_exists(object) {
1253 return Err(EditSectionError::ObjectDoesNotExist);
1254 }
1255 Ok(())
1256 }
1257
1258 fn ensure_effect_exists(&self, effect: EffectHandle) -> EditSectionResult<()> {
1259 if !self.effect_exists(effect) {
1260 return Err(EditSectionError::EffectDoesNotExist);
1261 }
1262 Ok(())
1263 }
1264
1265 pub fn objects_in_layer(
1267 &self,
1268 layer: usize,
1269 ) -> EditSectionLayerObjectsIterator<'_, ReadSection> {
1270 EditSectionLayerObjectsIterator::new(self, layer)
1271 }
1272
1273 pub fn layer<'a>(&'a self, layer: usize) -> EditSectionLayerCaller<'a, ReadSection> {
1275 EditSectionLayerCaller::new(self, layer)
1276 }
1277
1278 pub fn object<'a>(&'a self, object: ObjectHandle) -> EditSectionObjectCaller<'a, ReadSection> {
1280 EditSectionObjectCaller::new(self, object)
1281 }
1282
1283 pub fn effect<'a>(&'a self, effect: EffectHandle) -> EditSectionEffectCaller<'a, ReadSection> {
1285 EditSectionEffectCaller::new(self, effect)
1286 }
1287}
1288
1289impl EditSection {
1290 pub unsafe fn from_raw(ptr: *mut aviutl2_sys::plugin2::EDIT_SECTION) -> Self {
1296 let info = unsafe { EditInfo::from_raw((*ptr).info) };
1297 Self {
1298 internal: ptr,
1299 info,
1300 read_section: ReadSection { internal: ptr },
1301 }
1302 }
1303
1304 pub fn create_object_from_alias(
1320 &self,
1321 alias: &str,
1322 layer: usize,
1323 frame: usize,
1324 length: usize,
1325 ) -> EditSectionResult<ObjectHandle> {
1326 let c_alias = std::ffi::CString::new(alias)?;
1327 let object_handle = unsafe {
1328 ((*self.internal).create_object_from_alias)(
1329 c_alias.as_ptr(),
1330 layer.try_into()?,
1331 frame.try_into()?,
1332 length.try_into()?,
1333 )
1334 };
1335 if object_handle.is_null() {
1336 return Err(EditSectionError::ApiCallFailed);
1337 }
1338 Ok(ObjectHandle {
1339 internal: object_handle,
1340 })
1341 }
1342
1343 pub fn set_object_name(
1349 &self,
1350 object: ObjectHandle,
1351 name: Option<&str>,
1352 ) -> EditSectionResult<()> {
1353 self.read_section.ensure_object_exists(object)?;
1354 match name {
1355 None => {
1356 unsafe { ((*self.internal).set_object_name)(object.internal, std::ptr::null()) };
1357 Ok(())
1358 }
1359 Some(name) => {
1360 let c_name = crate::common::CWString::new(name)?;
1361 unsafe {
1362 ((*self.internal).set_object_name)(object.internal, c_name.as_ptr());
1363 }
1364 Ok(())
1365 }
1366 }
1367 }
1368
1369 pub fn set_object_effect_item(
1379 &self,
1380 object: ObjectHandle,
1381 effect_name: &str,
1382 effect_index: usize,
1383 item: &str,
1384 value: &str,
1385 ) -> EditSectionResult<()> {
1386 self.read_section.ensure_object_exists(object)?;
1387 let c_effect_name = crate::common::CWString::new(&effect_key(effect_name, effect_index))?;
1388 let c_item = crate::common::CWString::new(item)?;
1389 let c_value = std::ffi::CString::new(value)?;
1390 let success = unsafe {
1391 ((*self.internal).set_object_item_value)(
1392 object.internal,
1393 c_effect_name.as_ptr(),
1394 c_item.as_ptr(),
1395 c_value.as_ptr(),
1396 )
1397 };
1398 if !success {
1399 return Err(EditSectionError::ApiCallFailed);
1400 }
1401 Ok(())
1402 }
1403
1404 pub fn set_effect_data_value(
1406 &self,
1407 effect: EffectHandle,
1408 item: &str,
1409 data: &[u8],
1410 ) -> EditSectionResult<()> {
1411 self.read_section.ensure_effect_exists(effect)?;
1412 let c_item = crate::common::CWString::new(item)?;
1413 let success = unsafe {
1414 ((*self.internal).set_effect_data_value)(
1415 effect.internal,
1416 c_item.as_ptr(),
1417 data.as_ptr() as *mut std::ffi::c_void,
1418 data.len().try_into()?,
1419 )
1420 };
1421 if !success {
1422 return Err(EditSectionError::ApiCallFailed);
1423 }
1424 Ok(())
1425 }
1426
1427 pub fn set_effect_data_value_with<T>(
1429 &self,
1430 effect: EffectHandle,
1431 item: &str,
1432 data: &T,
1433 ) -> EditSectionResult<()> {
1434 self.read_section.ensure_effect_exists(effect)?;
1435 let c_item = crate::common::CWString::new(item)?;
1436 let success = unsafe {
1437 ((*self.internal).set_effect_data_value)(
1438 effect.internal,
1439 c_item.as_ptr(),
1440 data as *const T as *mut std::ffi::c_void,
1441 std::mem::size_of::<T>().try_into()?,
1442 )
1443 };
1444 if !success {
1445 return Err(EditSectionError::ApiCallFailed);
1446 }
1447 Ok(())
1448 }
1449
1450 pub fn move_object(
1452 &self,
1453 object: ObjectHandle,
1454 new_layer: usize,
1455 new_start_frame: usize,
1456 ) -> EditSectionResult<()> {
1457 self.read_section.ensure_object_exists(object)?;
1458 let success = unsafe {
1459 ((*self.internal).move_object)(
1460 object.internal,
1461 new_layer.try_into()?,
1462 new_start_frame.try_into()?,
1463 )
1464 };
1465 if !success {
1466 return Err(EditSectionError::ApiCallFailed);
1467 }
1468 Ok(())
1469 }
1470
1471 pub fn delete_object(&self, object: ObjectHandle) -> EditSectionResult<()> {
1473 self.read_section.ensure_object_exists(object)?;
1474 unsafe { ((*self.internal).delete_object)(object.internal) };
1475 Ok(())
1476 }
1477
1478 pub fn set_focus_object(&self, object: Option<ObjectHandle>) -> EditSectionResult<()> {
1484 if let Some(object) = object {
1485 self.read_section.ensure_object_exists(object)?;
1486 unsafe { ((*self.internal).set_focus_object)(object.internal) };
1487 } else {
1488 unsafe { ((*self.internal).set_focus_object)(std::ptr::null_mut()) };
1489 }
1490 Ok(())
1491 }
1492
1493 pub fn get_project_file<'handle>(
1495 &'handle self,
1496 edit_handle: &crate::generic::EditHandle,
1497 ) -> crate::generic::ProjectFile<'handle> {
1498 let pf_ptr = unsafe { ((*self.internal).get_project_file)(edit_handle.internal) };
1499 unsafe { crate::generic::ProjectFile::from_raw(pf_ptr) }
1500 }
1501
1502 pub fn get_mouse_layer_frame(&self) -> EditSectionResult<Option<LayerFrameData>> {
1509 let mut layer = 0;
1510 let mut frame = 0;
1511 let on_layer_edit =
1512 unsafe { ((*self.internal).get_mouse_layer_frame)(&mut layer, &mut frame) };
1513 if on_layer_edit {
1514 Ok(Some(LayerFrameData {
1515 layer: layer.try_into()?,
1516 frame: frame.try_into()?,
1517 }))
1518 } else {
1519 Ok(None)
1520 }
1521 }
1522
1523 pub fn pos_to_layer_frame(&self, x: i32, y: i32) -> EditSectionResult<Option<LayerFrameData>> {
1525 let mut layer = 0;
1526 let mut frame = 0;
1527 let on_layer_edit =
1528 unsafe { ((*self.internal).pos_to_layer_frame)(x, y, &mut layer, &mut frame) };
1529 if on_layer_edit {
1530 Ok(Some(LayerFrameData {
1531 layer: layer.try_into()?,
1532 frame: frame.try_into()?,
1533 }))
1534 } else {
1535 Ok(None)
1536 }
1537 }
1538
1539 pub fn create_object_from_media_file<P: AsRef<std::path::Path>>(
1548 &self,
1549 file_path: P,
1550 layer: usize,
1551 frame: usize,
1552 length: Option<usize>,
1553 ) -> EditSectionResult<ObjectHandle> {
1554 let c_file_path = crate::common::CWString::new(&file_path.as_ref().to_string_lossy())?;
1555 let object_handle = unsafe {
1556 ((*self.internal).create_object_from_media_file)(
1557 c_file_path.as_ptr(),
1558 layer.try_into()?,
1559 frame.try_into()?,
1560 length.unwrap_or(0).try_into()?,
1561 )
1562 };
1563 if object_handle.is_null() {
1564 return Err(EditSectionError::ApiCallFailed);
1565 }
1566 Ok(ObjectHandle {
1567 internal: object_handle,
1568 })
1569 }
1570
1571 pub fn create_object(
1580 &self,
1581 effect: &str,
1582 layer: usize,
1583 frame: usize,
1584 length: Option<usize>,
1585 ) -> EditSectionResult<ObjectHandle> {
1586 let c_effect = crate::common::CWString::new(effect)?;
1587 let object_handle = unsafe {
1588 ((*self.internal).create_object)(
1589 c_effect.as_ptr(),
1590 layer.try_into()?,
1591 frame.try_into()?,
1592 length.unwrap_or(0).try_into()?,
1593 )
1594 };
1595 if object_handle.is_null() {
1596 return Err(EditSectionError::ApiCallFailed);
1597 }
1598 Ok(ObjectHandle {
1599 internal: object_handle,
1600 })
1601 }
1602
1603 pub fn create_effect(
1614 &self,
1615 object: ObjectHandle,
1616 effect: &str,
1617 ) -> EditSectionResult<EffectHandle> {
1618 self.read_section.ensure_object_exists(object)?;
1619 let c_effect = crate::common::CWString::new(effect)?;
1620 let effect_handle =
1621 unsafe { ((*self.internal).create_effect)(object.internal, c_effect.as_ptr()) };
1622 if effect_handle.is_null() {
1623 return Err(EditSectionError::ApiCallFailed);
1624 }
1625 Ok(EffectHandle {
1626 internal: effect_handle,
1627 })
1628 }
1629
1630 pub fn delete_effect(
1632 &self,
1633 object: ObjectHandle,
1634 effect: EffectHandle,
1635 ) -> EditSectionResult<()> {
1636 self.read_section.ensure_object_exists(object)?;
1637 self.read_section.ensure_effect_exists(effect)?;
1638 let success = unsafe { ((*self.internal).delete_effect)(object.internal, effect.internal) };
1639 if !success {
1640 return Err(EditSectionError::ApiCallFailed);
1641 }
1642 Ok(())
1643 }
1644
1645 pub fn create_object_section(
1647 &self,
1648 object: ObjectHandle,
1649 frame: usize,
1650 ) -> EditSectionResult<()> {
1651 self.read_section.ensure_object_exists(object)?;
1652 let success =
1653 unsafe { ((*self.internal).create_object_section)(object.internal, frame.try_into()?) };
1654 if !success {
1655 return Err(EditSectionError::ApiCallFailed);
1656 }
1657 Ok(())
1658 }
1659
1660 pub fn delete_object_section(
1662 &self,
1663 object: ObjectHandle,
1664 section: usize,
1665 ) -> EditSectionResult<()> {
1666 self.read_section.ensure_object_exists(object)?;
1667 let success = unsafe {
1668 ((*self.internal).delete_object_section)(object.internal, section.try_into()?)
1669 };
1670 if !success {
1671 return Err(EditSectionError::ApiCallFailed);
1672 }
1673 Ok(())
1674 }
1675
1676 pub fn move_object_section(
1683 &self,
1684 object: ObjectHandle,
1685 section: usize,
1686 new_frame: usize,
1687 ) -> EditSectionResult<()> {
1688 self.read_section.ensure_object_exists(object)?;
1689 let success = unsafe {
1690 ((*self.internal).move_object_section)(
1691 object.internal,
1692 section.try_into()?,
1693 new_frame.try_into()?,
1694 )
1695 };
1696 if !success {
1697 return Err(EditSectionError::ApiCallFailed);
1698 }
1699 Ok(())
1700 }
1701
1702 pub fn move_effect(
1708 &self,
1709 object: ObjectHandle,
1710 effect: EffectHandle,
1711 index: usize,
1712 ) -> EditSectionResult<usize> {
1713 self.read_section.ensure_object_exists(object)?;
1714 self.read_section.ensure_effect_exists(effect)?;
1715 let success = unsafe {
1716 ((*self.internal).move_effect)(object.internal, effect.internal, index.try_into()?)
1717 };
1718 if success == -1 {
1719 return Err(EditSectionError::ApiCallFailed);
1720 }
1721 Ok(success.try_into()?)
1722 }
1723
1724 pub fn set_cursor_layer_frame(&self, layer: usize, frame: usize) -> EditSectionResult<()> {
1730 unsafe {
1731 ((*self.internal).set_cursor_layer_frame)(layer.try_into()?, frame.try_into()?);
1732 }
1733 Ok(())
1734 }
1735
1736 pub fn set_display_layer_frame(&self, layer: usize, frame: usize) -> EditSectionResult<()> {
1742 unsafe {
1743 ((*self.internal).set_display_layer_frame)(layer.try_into()?, frame.try_into()?);
1744 }
1745 Ok(())
1746 }
1747
1748 pub fn set_select_range(&self, start: usize, end: usize) -> EditSectionResult<()> {
1754 unsafe {
1755 ((*self.internal).set_select_range)(start.try_into()?, end.try_into()?);
1756 }
1757 Ok(())
1758 }
1759
1760 pub fn clear_select_range(&self) -> EditSectionResult<()> {
1762 unsafe {
1763 ((*self.internal).set_select_range)(-1, -1);
1764 }
1765 Ok(())
1766 }
1767
1768 pub fn set_grid_bpm_list(&self, bpm_info: &[BpmInfo]) -> EditSectionResult<()> {
1770 let mut raw_bpm_info = bpm_info
1771 .iter()
1772 .copied()
1773 .map(aviutl2_sys::plugin2::BPM_INFO::from)
1774 .collect::<Vec<_>>();
1775 unsafe {
1776 ((*self.internal).set_grid_bpm_list)(
1777 raw_bpm_info.as_mut_ptr(),
1778 raw_bpm_info.len().try_into()?,
1779 std::mem::size_of::<aviutl2_sys::plugin2::BPM_INFO>().try_into()?,
1780 );
1781 }
1782 Ok(())
1783 }
1784
1785 pub fn set_layer_name(&self, layer: usize, name: Option<&str>) -> EditSectionResult<()> {
1788 match name {
1789 None => {
1790 unsafe { ((*self.internal).set_layer_name)(layer.try_into()?, std::ptr::null()) };
1791 Ok(())
1792 }
1793 Some(name) => {
1794 let c_name = crate::common::CWString::new(name)?;
1795 unsafe {
1796 ((*self.internal).set_layer_name)(layer.try_into()?, c_name.as_ptr());
1797 }
1798 Ok(())
1799 }
1800 }
1801 }
1802
1803 pub fn set_scene_name(&self, name: &str) -> EditSectionResult<()> {
1809 let c_name = crate::common::CWString::new(name)?;
1810 unsafe { ((*self.internal).set_scene_name)(c_name.as_ptr()) };
1811 Ok(())
1812 }
1813
1814 pub fn set_scene_size(&self, width: usize, height: usize) -> EditSectionResult<()> {
1820 unsafe {
1821 ((*self.internal).set_scene_size)(width.try_into()?, height.try_into()?);
1822 }
1823 Ok(())
1824 }
1825
1826 pub fn set_scene_fps(&self, fps: Rational32) -> EditSectionResult<()> {
1832 unsafe {
1833 ((*self.internal).set_scene_frame_rate)(*fps.numer(), *fps.denom());
1834 }
1835 Ok(())
1836 }
1837
1838 pub fn set_scene_sample_rate(&self, sample_rate: usize) -> EditSectionResult<()> {
1844 unsafe {
1845 ((*self.internal).set_scene_sample_rate)(sample_rate.try_into()?);
1846 }
1847 Ok(())
1848 }
1849
1850 pub fn set_layer_enable(&self, layer: usize, enable: bool) -> EditSectionResult<()> {
1852 unsafe {
1853 ((*self.internal).set_layer_enable)(layer.try_into()?, enable);
1854 }
1855 Ok(())
1856 }
1857
1858 pub fn set_layer_lock(&self, layer: usize, lock: bool) -> EditSectionResult<()> {
1860 unsafe {
1861 ((*self.internal).set_layer_lock)(layer.try_into()?, lock);
1862 }
1863 Ok(())
1864 }
1865
1866 pub fn set_effect_enable(&self, effect: EffectHandle, enable: bool) -> EditSectionResult<()> {
1868 self.read_section.ensure_effect_exists(effect)?;
1869 unsafe {
1870 ((*self.internal).set_effect_enable)(effect.internal, enable);
1871 }
1872 Ok(())
1873 }
1874
1875 pub fn set_effect_lock(&self, effect: EffectHandle, lock: bool) -> EditSectionResult<()> {
1877 self.read_section.ensure_effect_exists(effect)?;
1878 unsafe {
1879 ((*self.internal).set_effect_lock)(effect.internal, lock);
1880 }
1881 Ok(())
1882 }
1883
1884 pub fn set_effect_item_value(
1886 &self,
1887 effect: EffectHandle,
1888 item: &str,
1889 value: &str,
1890 ) -> EditSectionResult<()> {
1891 self.read_section.ensure_effect_exists(effect)?;
1892 let c_item = crate::common::CWString::new(item)?;
1893 let c_value = std::ffi::CString::new(value)?;
1894 let success = unsafe {
1895 ((*self.internal).set_effect_item_value)(
1896 effect.internal,
1897 c_item.as_ptr(),
1898 c_value.as_ptr(),
1899 )
1900 };
1901 if !success {
1902 return Err(EditSectionError::ApiCallFailed);
1903 }
1904 Ok(())
1905 }
1906
1907 pub fn set_mark_frame(&self, frame: usize, memo: &str) -> EditSectionResult<()> {
1909 let c_memo = crate::common::CWString::new(memo)?;
1910 unsafe {
1911 ((*self.internal).set_mark_frame)(
1912 frame.try_into()?,
1913 if memo.is_empty() {
1914 std::ptr::null()
1915 } else {
1916 c_memo.as_ptr()
1917 },
1918 )
1919 };
1920 Ok(())
1921 }
1922
1923 pub fn clear_mark_frame(&self, frame: usize) -> EditSectionResult<()> {
1925 unsafe { ((*self.internal).clear_mark_frame)(frame.try_into()?) };
1926 Ok(())
1927 }
1928
1929 pub fn move_mark_frame(&self, old_frame: usize, new_frame: usize) -> EditSectionResult<()> {
1931 let success = unsafe {
1932 ((*self.internal).move_mark_frame)(old_frame.try_into()?, new_frame.try_into()?)
1933 };
1934 if !success {
1935 return Err(EditSectionError::ApiCallFailed);
1936 }
1937 Ok(())
1938 }
1939
1940 pub fn set_palette_info(&self, name: &str, palette: &PaletteInfo) -> EditSectionResult<()> {
1942 let name = crate::common::CWString::new(name)?;
1943 let mut raw_palette = palette.to_raw();
1944 let success = unsafe {
1945 ((*self.internal).set_palette_info)(
1946 name.as_ptr(),
1947 &mut raw_palette as *mut aviutl2_sys::plugin2::PALETTE_INFO,
1948 std::mem::size_of::<aviutl2_sys::plugin2::PALETTE_INFO>().try_into()?,
1949 )
1950 };
1951 if !success {
1952 return Err(EditSectionError::ApiCallFailed);
1953 }
1954 Ok(())
1955 }
1956
1957 pub fn set_edited_state(&self) -> EditSectionResult<()> {
1963 unsafe { ((*self.internal).set_edited_state)() };
1964 Ok(())
1965 }
1966
1967 pub fn layers(&self) -> EditSectionLayersIterator<'_> {
1969 EditSectionLayersIterator::new(self)
1970 }
1971 pub fn objects_in_layer(
1973 &self,
1974 layer: usize,
1975 ) -> EditSectionLayerObjectsIterator<'_, EditSection> {
1976 EditSectionLayerObjectsIterator::new(self, layer)
1977 }
1978
1979 pub fn layer<'a>(&'a self, layer: usize) -> EditSectionLayerCaller<'a, EditSection> {
1981 EditSectionLayerCaller::new(self, layer)
1982 }
1983 pub fn object<'a>(&'a self, object: ObjectHandle) -> EditSectionObjectCaller<'a, EditSection> {
1985 EditSectionObjectCaller::new(self, object)
1986 }
1987
1988 pub fn effect<'a>(&'a self, effect: EffectHandle) -> EditSectionEffectCaller<'a, EditSection> {
1990 EditSectionEffectCaller::new(self, effect)
1991 }
1992}
1993
1994mod sealed {
1995 pub trait Sealed {}
1996 impl Sealed for super::ReadSection {}
1997 impl Sealed for super::EditSection {}
1998}
1999
2000pub trait ReadSectionProvider: sealed::Sealed {
2001 fn as_read_section(&self) -> &ReadSection;
2002}
2003
2004impl ReadSectionProvider for ReadSection {
2005 fn as_read_section(&self) -> &ReadSection {
2006 self
2007 }
2008}
2009
2010impl ReadSectionProvider for EditSection {
2011 fn as_read_section(&self) -> &ReadSection {
2012 &self.read_section
2013 }
2014}
2015
2016pub struct EditSectionObjectCaller<'a, S: ReadSectionProvider> {
2020 edit_section: &'a S,
2021 pub handle: ObjectHandle,
2022}
2023impl<'a, S: ReadSectionProvider> EditSectionObjectCaller<'a, S> {
2024 pub fn new(edit_section: &'a S, object: ObjectHandle) -> Self {
2025 Self {
2026 edit_section,
2027 handle: object,
2028 }
2029 }
2030}
2031
2032impl<S: ReadSectionProvider> std::ops::Deref for EditSectionObjectCaller<'_, S> {
2033 type Target = ObjectHandle;
2034
2035 fn deref(&self) -> &Self::Target {
2036 &self.handle
2037 }
2038}
2039
2040impl<S> EditSectionObjectCaller<'_, S>
2041where
2042 S: ReadSectionProvider,
2043{
2044 fn read_section(&self) -> &ReadSection {
2045 self.edit_section.as_read_section()
2046 }
2047
2048 pub fn get_layer_frame(&self) -> EditSectionResult<ObjectLayerFrame> {
2050 self.read_section().get_object_layer_frame(self.handle)
2051 }
2052
2053 pub fn get_alias(&self) -> EditSectionResult<String> {
2055 self.read_section().get_object_alias(self.handle)
2056 }
2057
2058 #[cfg(feature = "aviutl2-alias")]
2060 pub fn get_alias_parsed(&self) -> EditSectionResult<aviutl2_alias::Table> {
2061 self.read_section()
2062 .get_object_alias(self.handle)?
2063 .parse()
2064 .map_err(Into::into)
2065 }
2066
2067 pub fn count_effect(&self, effect: &str) -> EditSectionResult<usize> {
2077 self.read_section().count_object_effect(self.handle, effect)
2078 }
2079
2080 pub fn find_effect(
2082 &self,
2083 effect_name: &str,
2084 effect_index: usize,
2085 ) -> EditSectionResult<EffectHandle> {
2086 self.read_section()
2087 .find_effect(self.handle, effect_name, effect_index)
2088 }
2089
2090 pub fn get_first_effect(&self) -> EditSectionResult<EffectHandle> {
2092 self.read_section().get_first_effect(self.handle)
2093 }
2094
2095 pub fn get_effects(&self) -> EditSectionResult<Vec<EffectHandle>> {
2097 self.read_section().get_effects(self.handle)
2098 }
2099
2100 pub fn get_effect_item(
2108 &self,
2109 effect_name: &str,
2110 effect_index: usize,
2111 item: &str,
2112 ) -> EditSectionResult<String> {
2113 self.read_section()
2114 .get_object_effect_item(self.handle, effect_name, effect_index, item)
2115 }
2116
2117 #[cfg(feature = "aviutl2-alias")]
2123 pub fn get_effect_item_parsed<T: aviutl2_alias::FromTableValue>(
2124 &self,
2125 effect_name: &str,
2126 effect_index: usize,
2127 item: &str,
2128 ) -> Result<T, EditSectionParsedError<<T as aviutl2_alias::FromTableValue>::Err>>
2129 where
2130 <T as aviutl2_alias::FromTableValue>::Err: std::error::Error + Sync + Send + 'static,
2131 {
2132 let value_str = self.get_effect_item(effect_name, effect_index, item)?;
2133 T::from_table_value(&value_str).map_err(EditSectionParsedError::ParseError)
2134 }
2135
2136 pub fn exists(&self) -> bool {
2138 self.read_section().object_exists(self.handle)
2139 }
2140
2141 pub fn get_name(&self) -> EditSectionResult<Option<String>> {
2147 self.read_section().get_object_name(self.handle)
2148 }
2149
2150 pub fn get_section_num(&self) -> EditSectionResult<usize> {
2152 self.read_section().get_object_section_num(self.handle)
2153 }
2154
2155 pub fn get_section_frame(&self, section: usize) -> EditSectionResult<usize> {
2157 self.read_section()
2158 .get_object_section_frame(self.handle, section)
2159 }
2160
2161 pub fn get_section_frames(&self) -> EditSectionResult<Vec<usize>> {
2163 self.read_section().get_object_section_frames(self.handle)
2164 }
2165
2166 pub fn get_track_value(
2168 &self,
2169 effect_name: &str,
2170 effect_index: usize,
2171 item: &str,
2172 frame: f64,
2173 ) -> EditSectionResult<f64> {
2174 self.read_section().get_object_track_value(
2175 self.handle,
2176 effect_name,
2177 effect_index,
2178 item,
2179 frame,
2180 )
2181 }
2182
2183 pub fn get_check_value(
2185 &self,
2186 effect_name: &str,
2187 effect_index: usize,
2188 item: &str,
2189 frame: usize,
2190 ) -> EditSectionResult<bool> {
2191 self.read_section().get_object_check_value(
2192 self.handle,
2193 effect_name,
2194 effect_index,
2195 item,
2196 frame,
2197 )
2198 }
2199
2200 pub fn get_track_info(
2202 &self,
2203 effect_name: &str,
2204 effect_index: usize,
2205 item: &str,
2206 ) -> EditSectionResult<TrackInfo> {
2207 self.read_section()
2208 .get_object_track_info(self.handle, effect_name, effect_index, item)
2209 }
2210
2211 pub fn get_track_group_names(
2213 &self,
2214 effect_name: &str,
2215 effect_index: usize,
2216 group_name: &str,
2217 ) -> EditSectionResult<Vec<String>> {
2218 self.read_section().get_object_track_group_names(
2219 self.handle,
2220 effect_name,
2221 effect_index,
2222 group_name,
2223 )
2224 }
2225}
2226
2227impl EditSectionObjectCaller<'_, EditSection> {
2228 pub fn create_effect(&self, effect: &str) -> EditSectionResult<EffectHandle> {
2230 self.edit_section.create_effect(self.handle, effect)
2231 }
2232
2233 pub fn delete_effect(&self, effect: EffectHandle) -> EditSectionResult<()> {
2235 self.edit_section.delete_effect(self.handle, effect)
2236 }
2237
2238 pub fn move_effect(&self, effect: EffectHandle, index: usize) -> EditSectionResult<usize> {
2240 self.edit_section.move_effect(self.handle, effect, index)
2241 }
2242
2243 pub fn create_section(&self, frame: usize) -> EditSectionResult<()> {
2245 self.edit_section.create_object_section(self.handle, frame)
2246 }
2247
2248 pub fn delete_section(&self, section: usize) -> EditSectionResult<()> {
2250 self.edit_section
2251 .delete_object_section(self.handle, section)
2252 }
2253
2254 pub fn move_section(&self, section: usize, new_frame: usize) -> EditSectionResult<()> {
2258 self.edit_section
2259 .move_object_section(self.handle, section, new_frame)
2260 }
2261
2262 pub fn set_effect_item(
2271 &self,
2272 effect_name: &str,
2273 effect_index: usize,
2274 item: &str,
2275 value: &str,
2276 ) -> EditSectionResult<()> {
2277 self.edit_section.set_object_effect_item(
2278 self.handle,
2279 effect_name,
2280 effect_index,
2281 item,
2282 value,
2283 )
2284 }
2285
2286 pub fn move_object(&self, new_layer: usize, new_start_frame: usize) -> EditSectionResult<()> {
2293 self.edit_section
2294 .move_object(self.handle, new_layer, new_start_frame)
2295 }
2296
2297 pub fn delete_object(&self) -> EditSectionResult<()> {
2299 self.edit_section.delete_object(self.handle)
2300 }
2301
2302 pub fn set_focus_object(&self) -> EditSectionResult<()> {
2308 self.edit_section.set_focus_object(Some(self.handle))
2309 }
2310
2311 pub fn set_name(&self, name: Option<&str>) -> EditSectionResult<()> {
2314 self.edit_section.set_object_name(self.handle, name)
2315 }
2316}
2317
2318pub struct EditSectionEffectCaller<'a, S: ReadSectionProvider> {
2322 edit_section: &'a S,
2323 pub handle: EffectHandle,
2324}
2325impl<'a, S: ReadSectionProvider> EditSectionEffectCaller<'a, S> {
2326 pub fn new(edit_section: &'a S, effect: EffectHandle) -> Self {
2327 Self {
2328 edit_section,
2329 handle: effect,
2330 }
2331 }
2332}
2333
2334impl<S: ReadSectionProvider> std::ops::Deref for EditSectionEffectCaller<'_, S> {
2335 type Target = EffectHandle;
2336
2337 fn deref(&self) -> &Self::Target {
2338 &self.handle
2339 }
2340}
2341
2342impl<S> EditSectionEffectCaller<'_, S>
2343where
2344 S: ReadSectionProvider,
2345{
2346 fn read_section(&self) -> &ReadSection {
2347 self.edit_section.as_read_section()
2348 }
2349
2350 pub fn exists(&self) -> bool {
2352 self.read_section().effect_exists(self.handle)
2353 }
2354
2355 pub fn get_name(&self) -> EditSectionResult<String> {
2357 self.read_section().get_effect_name(self.handle)
2358 }
2359
2360 pub fn get_enable(&self) -> EditSectionResult<bool> {
2362 self.read_section().get_effect_enable(self.handle)
2363 }
2364
2365 pub fn get_lock(&self) -> EditSectionResult<bool> {
2367 self.read_section().get_effect_lock(self.handle)
2368 }
2369
2370 pub fn get_item_value(&self, item: &str) -> EditSectionResult<String> {
2372 self.read_section().get_effect_item_value(self.handle, item)
2373 }
2374
2375 #[cfg(feature = "aviutl2-alias")]
2377 pub fn get_item_value_parsed<T: aviutl2_alias::FromTableValue>(
2378 &self,
2379 item: &str,
2380 ) -> Result<T, EditSectionParsedError<<T as aviutl2_alias::FromTableValue>::Err>>
2381 where
2382 <T as aviutl2_alias::FromTableValue>::Err: std::error::Error + Sync + Send + 'static,
2383 {
2384 let value_str = self.get_item_value(item)?;
2385 T::from_table_value(&value_str).map_err(EditSectionParsedError::ParseError)
2386 }
2387
2388 pub fn get_data_size(&self, item: &str) -> EditSectionResult<usize> {
2390 self.read_section().get_effect_data_size(self.handle, item)
2391 }
2392
2393 pub fn get_data_value(&self, item: &str) -> EditSectionResult<Vec<u8>> {
2395 self.read_section().get_effect_data_value(self.handle, item)
2396 }
2397
2398 pub unsafe fn get_data_value_as<T>(&self, item: &str) -> EditSectionResult<T> {
2404 unsafe {
2405 self.read_section()
2406 .get_effect_data_value_as(self.handle, item)
2407 }
2408 }
2409
2410 pub fn get_track_value(&self, item: &str, frame: f64) -> EditSectionResult<f64> {
2412 self.read_section()
2413 .get_effect_track_value(self.handle, item, frame)
2414 }
2415
2416 pub fn get_check_value(&self, item: &str, frame: usize) -> EditSectionResult<bool> {
2418 self.read_section()
2419 .get_effect_check_value(self.handle, item, frame)
2420 }
2421
2422 pub fn get_track_info(&self, item: &str) -> EditSectionResult<TrackInfo> {
2424 self.read_section().get_effect_track_info(self.handle, item)
2425 }
2426}
2427
2428impl EditSectionEffectCaller<'_, EditSection> {
2429 pub fn set_enable(&self, enable: bool) -> EditSectionResult<()> {
2431 self.edit_section.set_effect_enable(self.handle, enable)
2432 }
2433
2434 pub fn set_lock(&self, lock: bool) -> EditSectionResult<()> {
2436 self.edit_section.set_effect_lock(self.handle, lock)
2437 }
2438
2439 pub fn set_item_value(&self, item: &str, value: &str) -> EditSectionResult<()> {
2441 self.edit_section
2442 .set_effect_item_value(self.handle, item, value)
2443 }
2444
2445 pub fn set_data_value(&self, item: &str, data: &[u8]) -> EditSectionResult<()> {
2447 self.edit_section
2448 .set_effect_data_value(self.handle, item, data)
2449 }
2450
2451 pub fn set_data_value_with<T>(&self, item: &str, data: &T) -> EditSectionResult<()> {
2453 self.edit_section
2454 .set_effect_data_value_with(self.handle, item, data)
2455 }
2456}
2457
2458pub struct EditSectionLayerCaller<'a, S> {
2462 edit_section: &'a S,
2463 pub index: usize,
2464}
2465impl<'a, S> EditSectionLayerCaller<'a, S> {
2466 pub fn new(edit_section: &'a S, layer: usize) -> Self {
2467 Self {
2468 edit_section,
2469 index: layer,
2470 }
2471 }
2472}
2473
2474impl<S> EditSectionLayerCaller<'_, S>
2475where
2476 S: ReadSectionProvider,
2477{
2478 fn read_section(&self) -> &ReadSection {
2479 self.edit_section.as_read_section()
2480 }
2481
2482 pub fn find_object_after(&self, frame: usize) -> EditSectionResult<Option<ObjectHandle>> {
2488 self.read_section().find_object_after(self.index, frame)
2489 }
2490
2491 pub fn get_name(&self) -> EditSectionResult<Option<String>> {
2493 self.read_section().get_layer_name(self.index)
2494 }
2495
2496 pub fn get_enable(&self) -> EditSectionResult<bool> {
2498 self.read_section().get_layer_enable(self.index)
2499 }
2500
2501 pub fn get_lock(&self) -> EditSectionResult<bool> {
2503 self.read_section().get_layer_lock(self.index)
2504 }
2505
2506 pub fn objects(&self) -> EditSectionLayerObjectsIterator<'_, S> {
2509 EditSectionLayerObjectsIterator::new(self.edit_section, self.index)
2510 }
2511}
2512
2513impl EditSectionLayerCaller<'_, EditSection> {
2514 pub fn create_object_from_alias<P: AsRef<std::path::Path>>(
2520 &self,
2521 alias: &str,
2522 frame: usize,
2523 length: usize,
2524 ) -> EditSectionResult<ObjectHandle> {
2525 self.edit_section
2526 .create_object_from_alias(alias, self.index, frame, length)
2527 }
2528
2529 pub fn create_object_from_media_file<P: AsRef<std::path::Path>>(
2535 &self,
2536 file_path: P,
2537 frame: usize,
2538 length: Option<usize>,
2539 ) -> EditSectionResult<ObjectHandle> {
2540 self.edit_section
2541 .create_object_from_media_file(file_path, self.index, frame, length)
2542 }
2543
2544 pub fn create_object(
2550 &self,
2551 effect: &str,
2552 frame: usize,
2553 length: Option<usize>,
2554 ) -> EditSectionResult<ObjectHandle> {
2555 self.edit_section
2556 .create_object(effect, self.index, frame, length)
2557 }
2558
2559 pub fn set_name(&self, name: Option<&str>) -> EditSectionResult<()> {
2562 self.edit_section.set_layer_name(self.index, name)
2563 }
2564
2565 pub fn set_enable(&self, enable: bool) -> EditSectionResult<()> {
2567 self.edit_section.set_layer_enable(self.index, enable)
2568 }
2569
2570 pub fn set_lock(&self, lock: bool) -> EditSectionResult<()> {
2572 self.edit_section.set_layer_lock(self.index, lock)
2573 }
2574}
2575
2576#[derive(Debug, Clone)]
2578pub struct EditSectionLayersIterator<'a> {
2579 edit_section: &'a EditSection,
2580 current: usize,
2581 end: usize,
2582}
2583
2584impl<'a> EditSectionLayersIterator<'a> {
2585 fn new(edit_section: &'a EditSection) -> Self {
2586 Self {
2587 edit_section,
2588 current: 0,
2589 end: edit_section.info.layer_max.saturating_add(1),
2590 }
2591 }
2592}
2593
2594impl<'a> Iterator for EditSectionLayersIterator<'a> {
2595 type Item = EditSectionLayerCaller<'a, EditSection>;
2596
2597 fn next(&mut self) -> Option<Self::Item> {
2598 if self.current >= self.end {
2599 return None;
2600 }
2601 let layer = self.current;
2602 self.current += 1;
2603 Some(EditSectionLayerCaller::new(self.edit_section, layer))
2604 }
2605
2606 fn size_hint(&self) -> (usize, Option<usize>) {
2607 let len = self.end.saturating_sub(self.current);
2608 (len, Some(len))
2609 }
2610}
2611
2612impl<'a> DoubleEndedIterator for EditSectionLayersIterator<'a> {
2613 fn next_back(&mut self) -> Option<Self::Item> {
2614 if self.current >= self.end {
2615 return None;
2616 }
2617 self.end -= 1;
2618 Some(EditSectionLayerCaller::new(self.edit_section, self.end))
2619 }
2620}
2621
2622impl ExactSizeIterator for EditSectionLayersIterator<'_> {}
2623
2624#[derive(Debug, Clone)]
2627pub struct EditSectionLayerObjectsIterator<'a, S> {
2628 edit_section: &'a S,
2629 layer: usize,
2630 next_frame: usize,
2631}
2632
2633impl<'a, S> EditSectionLayerObjectsIterator<'a, S> {
2634 fn new(edit_section: &'a S, layer: usize) -> Self {
2635 Self {
2636 edit_section,
2637 layer,
2638 next_frame: 0,
2639 }
2640 }
2641}
2642
2643impl<S> Iterator for EditSectionLayerObjectsIterator<'_, S>
2644where
2645 S: ReadSectionProvider,
2646{
2647 type Item = (ObjectLayerFrame, ObjectHandle);
2648
2649 fn next(&mut self) -> Option<Self::Item> {
2650 let read_section = self.edit_section.as_read_section();
2651 let Ok(Some(handle)) = read_section.find_object_after(self.layer, self.next_frame) else {
2653 return None;
2654 };
2655
2656 let lf = match read_section.get_object_layer_frame(handle) {
2657 Ok(lf) => lf,
2658 Err(_) => return None,
2659 };
2660
2661 self.next_frame = lf.end.saturating_add(1);
2663
2664 Some((lf, handle))
2665 }
2666}
2667
2668fn effect_key(effect_name: &str, effect_index: usize) -> String {
2669 format!("{effect_name}:{effect_index}")
2670}